/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2009>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
using MyPhotoIndex.Controls;
using MyPhotoIndex.Utilities;
using System.Drawing;

namespace MyPhotoIndex
{
    public partial class Main
    {
        private delegate void ShowProcessAlertDelegate(ProcessInfoAlertParameters alertInfo);
        ShowProcessAlertDelegate ms_showProcessAlertDelegate;

        private ActiveProcess                       m_currentProcess;
        private Thread                              m_progressThread;
        private ProgressForm                        m_detailedProgressForm;
        private Queue<ProcessInfoAlertParameters>   m_alertQueue = new Queue<ProcessInfoAlertParameters>();
        private bool                                m_alertQueueProcessed;

        private delegate void voidDelegate();

        private void InitializeProgressBar()
        {
            ActiveProcesses.Instance.FirstProcessAddedEvent += new EventHandler(Instance_FirstProcessAddedEvent);
            ActiveProcesses.Instance.LastProcessRemovedEvent += new EventHandler(Instance_LastProcessRemovedEvent);
            ActiveProcesses.Instance.ProcessAddedEvent += new EventHandler(Instance_ProcessAddedEvent);
            ActiveProcesses.Instance.ProcessRemovedEvent += new EventHandler(Instance_ProcessRemovedEvent);
            ActiveProcesses.Instance.ProcessAlertEvent += new EventHandler<ProcessInfoAlertParameters>(Instance_ProcessAlertEvent);

            m_detailedProgressForm = new ProgressForm();
            toolStripProgressBar1.MouseHover += new EventHandler(toolStripProgressBar1_MouseHover);
            toolStripProgressBar1.MouseLeave += new EventHandler(toolStripProgressBar1_MouseLeave);

            ms_showProcessAlertDelegate = new ShowProcessAlertDelegate(AlertQueueShowAlert);

            //ApplicationContext.Instance.ProcessProgress.IsInfinite = true;
            //ApplicationContext.Instance.ProcessProgress.Running = true; ;

            //ActiveProcesses.Instance.Get(3).IsInfinite = true;
            //ActiveProcesses.Instance.Get(3).Running = true;

            //ActiveProcesses.Instance.Get(2).IsInfinite = true;
            //ActiveProcesses.Instance.Get(2).Running = true;
        }

        void Instance_ProcessAlertEvent(object sender, ProcessInfoAlertParameters e)
        {
            m_alertQueue.Enqueue(e);

            if (m_alertQueueProcessed == false)
            {
                m_alertQueueProcessed = true;
                ThreadPool.QueueUserWorkItem(new WaitCallback(AlertQueueProcessor));
            }
        }

        private void AlertQueueProcessor(object state)
        {
            while (m_alertQueue.Count > 0)
            {
                ProcessInfoAlertParameters alertParams = m_alertQueue.Dequeue();
                if (alertParams != null)
                {
                    this.Invoke(ms_showProcessAlertDelegate, new object[]{alertParams});
                }

                Thread.Sleep(5000);
            }
            m_alertQueueProcessed = false;
        }

        private void AlertQueueShowAlert(ProcessInfoAlertParameters alertInfo)
        {
            this.alertIconToolStripStatusLabel.Visible = true;

            ToolTip tt = new ToolTip();
            tt.IsBalloon = true;
            tt.UseAnimation = true;
            tt.ToolTipIcon = (ToolTipIcon)alertInfo.AlertType;

            Point location = toolStripProgressBar1.Bounds.Location;
            tt.Show(alertInfo.Message, statusStrip1, location, 5000);

       //     this.alertIconToolStripStatusLabel.Visible = false;
        }

        void toolStripProgressBar1_MouseLeave(object sender, EventArgs e)
        {
            if (m_detailedProgressForm.Visible == true)
            {
                m_detailedProgressForm.Visible = false;
            }
        }

        void toolStripProgressBar1_MouseHover(object sender, EventArgs e)
        {
            if (m_detailedProgressForm.Visible == false)
            {
                m_detailedProgressForm.Refresh();
                int finalHeight = m_detailedProgressForm.Height;
                m_detailedProgressForm.Height = 2;
                m_detailedProgressForm.FormBorderStyle = FormBorderStyle.None;
                m_detailedProgressForm.Left = toolStripProgressBar1.Bounds.X;
                m_detailedProgressForm.Top = -2;
                m_detailedProgressForm.Visible = true;

                for (int i = 2; i < finalHeight; i++)
                {
                    m_detailedProgressForm.Height = i;
                    m_detailedProgressForm.Top = this.Bottom - m_detailedProgressForm.Height - 30;
                }
            }
        }

        void Instance_ProcessRemovedEvent(object sender, EventArgs e)
        {
            m_currentProcess = ActiveProcesses.Instance[0];
            if (m_detailedProgressForm.Visible == true)
            {
                m_detailedProgressForm.Invoke(new voidDelegate(m_detailedProgressForm.Refresh));
            }
        }

        void Instance_ProcessAddedEvent(object sender, EventArgs e)
        {
            if (m_detailedProgressForm.Visible == true)
            {
                m_detailedProgressForm.Invoke(new voidDelegate(m_detailedProgressForm.Refresh));
            }
        }

        void Instance_LastProcessRemovedEvent(object sender, EventArgs e)
        {
            m_currentProcess = null;

            try
            {
                this.Invoke(new FormProgressShowDelegate(Main_FormProgressShow), new Object[] { false, ProgressBarStyle.Marquee });
            }
            catch(Exception ex)
            {
                Logger.Log(ex);
            }
        }

        void Instance_FirstProcessAddedEvent(object sender, EventArgs e)
        {
            m_currentProcess = ActiveProcesses.Instance[0];

            ProgressBarStyle progressStyle = m_currentProcess.IsInfinite ? ProgressBarStyle.Marquee : ProgressBarStyle.Continuous;
            this.Invoke(new FormProgressShowDelegate(Main_FormProgressShow), new Object[] { true, progressStyle });

            m_progressThread = new Thread(new ThreadStart(ProgressFunction));
            m_progressThread.Start();            
        }

        private void ProgressFunction()
        {
            while (m_currentProcess != null)
            {
                if (m_currentProcess != null)
                {
                    try
                    {
                        ProgressBarStyle progressStyle = m_currentProcess.IsInfinite ? ProgressBarStyle.Marquee : ProgressBarStyle.Continuous;
                        this.Invoke(new FormProgressUpdateDelegate(Main_FormProgressUpdate), new Object[] { m_currentProcess.Maximum, m_currentProcess.Value });
                        this.Invoke(new FormProgressShowDelegate(Main_FormProgressShow), new Object[] { true, progressStyle });
                    }
                    catch (Exception ex)
                    {
                        Logger.Log(ex);
                    }

                }

                Thread.Sleep(300);
                ActiveProcesses.Instance.Clear();
            }
        }

        internal void Main_FormProgressUpdate(int maxValue, int value)
        {
            RichToolStripProgressBar tspb = toolStripProgressBar1;
            if (maxValue > 0 &&
                tspb.ProgressBar.Maximum != maxValue)
            {
                tspb.ProgressBar.Maximum = maxValue;
            }

            if (value >= 0 &&
                tspb.ProgressBar.Value != value)
            {
                if (value > tspb.ProgressBar.Maximum)
                {
                    tspb.ProgressBar.Maximum = value + (value - tspb.ProgressBar.Maximum);
                }

                tspb.ProgressBar.Value = value;
            }

            //try
            //{
            //    bool update = false;
            //    if (string.Compare(m_currentProcess.ProcessDescription, tspb.ProgressBar.ToolTip) != 0)
            //    {
            //        update = true;
            //    }
            //}
            //catch (Exception ex)
            //{
            //    Logger.Log(ex);
            //}
        }

        void Main_FormProgressShow(bool show, ProgressBarStyle style)
        {
            bool wasVisible = toolStripProgressBar1.Visible;
            if (toolStripProgressBar1.ProgressBar.Style != style)
            {
                toolStripProgressBar1.ProgressBar.Style = style;
            }

            if (toolStripProgressBar1.Visible != show)
            {
                toolStripProgressBar1.Visible = show;
            }

            if (show == true &&
               wasVisible == false)
            {
                ToolTip tt = new ToolTip();
                tt.IsBalloon = true;
                tt.UseAnimation = true;
                tt.ToolTipIcon = ToolTipIcon.Info;

                Point location = toolStripProgressBar1.Bounds.Location;
                tt.Show(Resources.Resources.BackgroundProcessStarted, statusStrip1, location, 6000);
            }
            else
                if (show == false)
                {
                    this.alertIconToolStripStatusLabel.Visible = false;
                }
        }
    }
}
